#region File Description
//-----------------------------------------------------------------------------
// SampleGrid.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// UPDATE (13.06.11):   - Modified as "DrawableGameComponent"
//                      - Grid represented through grid and cell size
//                      - Dismissed the vertex buffer
//                      - Lines through origin have a different color
//
// Revision 4
//
//-----------------------------------------------------------------------------
#endregion

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Storage;

namespace NOVA.Utilities
{
    public class DebugGrid 
    {
        #region Members
        private int m_iGridSize;
        private int m_iCellSize;
        private Color m_gridColor;

        // Rendering
        private int m_iVertexCount;
        private int m_iPrimitiveCount;
        private BasicEffect m_effect;
        private Matrix m_matProjection;
        private Matrix m_matView;
        private Matrix m_matWorld;
        private GraphicsDevice m_device;
        private VertexPositionColor[] m_vertices;
        #endregion

        #region Properties
        public Color GridColor
        {
            get { return m_gridColor; }
            set 
            { 
                m_gridColor = value; 
                CalcGrid(); 
            }
        }
        public int GridSize
        {
            get { return m_iGridSize; }
            set 
            { 
                m_iGridSize = value;
                CalcGrid(); 
            }
        }
        public int CellSize
        {
            get { return m_iCellSize; }
            set 
            { 
                m_iCellSize = value;
                CalcGrid(); 
            }
        }
        public Matrix ProjectionMatrix
        {
            get { return m_matProjection; }
            set { m_matProjection = value; }
        }
        public Matrix WorldMatrix
        {
            get { return m_matWorld; }
            set { m_matWorld = value; }
        }
        public Matrix ViewMatrix
        {
            get { return m_matView; }
            set { m_matView = value; }
        }
        #endregion

        #region Constructor
        public DebugGrid(GraphicsDevice device) //: base(game)
        {
            m_device = device;

            m_effect = new BasicEffect(m_device);

            m_iGridSize = 100;
            m_iCellSize = 1;
            m_gridColor = Color.SteelBlue;//Color.DimGray;//Color.SteelBlue;
            m_matWorld = Matrix.Identity;
            m_matView = Matrix.Identity;
            m_matProjection = Matrix.Identity;

            CalcGrid();
        }
        #endregion           

        #region Public Methods

        public void CalcGrid()
        {
            Color color = new Color();
            int gridSize1 = m_iGridSize + 1;
            m_iPrimitiveCount = gridSize1 * 2 + 1;
            m_iVertexCount = m_iPrimitiveCount * 2;

            m_vertices = new VertexPositionColor[m_iVertexCount];

            float length = (float)m_iGridSize * m_iCellSize;
            float halfLength = length * 0.5f;

            int index = 0;
            
            for (int i = 0; i < gridSize1; ++i)
            {
                // The lines through the origin (at half of the array) should have the axis color
                if (i == gridSize1 / 2)
                {
                    m_vertices[index++] = new VertexPositionColor(new Vector3(-halfLength, 0.0f, i * m_iCellSize - halfLength), Color.Red);
                    m_vertices[index++] = new VertexPositionColor(new Vector3(halfLength, 0.0f, i * m_iCellSize - halfLength), Color.Red);

                    m_vertices[index++] = new VertexPositionColor(new Vector3(i * m_iCellSize - halfLength, 0.0f, -halfLength), Color.Blue);
                    m_vertices[index++] = new VertexPositionColor(new Vector3(i * m_iCellSize - halfLength, 0.0f, halfLength), Color.Blue);
                }
                else
                {
                    m_vertices[index++] = new VertexPositionColor(new Vector3(-halfLength, 0.0f, i * m_iCellSize - halfLength), m_gridColor);
                    m_vertices[index++] = new VertexPositionColor(new Vector3(halfLength, 0.0f, i * m_iCellSize - halfLength), m_gridColor);

                    m_vertices[index++] = new VertexPositionColor(new Vector3(i * m_iCellSize - halfLength, 0.0f, -halfLength), m_gridColor);
                    m_vertices[index++] = new VertexPositionColor(new Vector3(i * m_iCellSize - halfLength, 0.0f, halfLength), m_gridColor);
                }
            }

            m_vertices[index++] = new VertexPositionColor(new Vector3(0f,  100f, 0f), Color.Green);
            m_vertices[index++] = new VertexPositionColor(new Vector3(0f, -100f, 0f), Color.Green);
        }

        public void Dispose()
        {
            if (m_effect != null)
            {
                m_effect.Dispose();
                m_effect = null;
            }

            GC.SuppressFinalize(this);
        }

        #endregion

        #region Overrides

        public /*override*/ void Draw(GameTime gameTime)
        {
            m_effect.World = m_matWorld;
            m_effect.View = m_matView;
            m_effect.Projection = m_matProjection;
            m_effect.VertexColorEnabled = true;
            m_effect.LightingEnabled = false;

            for (int i = 0; i < m_effect.CurrentTechnique.Passes.Count; ++i)
            {
                m_effect.CurrentTechnique.Passes[i].Apply();
                m_device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, m_vertices, 0, m_iPrimitiveCount);                
            }                
                        
            //base.Draw(gameTime);
        }

        #endregion
    }
}
